package main

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"os/signal"
	"strings"
	"sync"

	socketio "github.com/zhouhui8915/go-socket.io-client"
)

type Team struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

type Match struct {
	ID      string
	HomeID  string
	AwayID  string
	Home    *Team
	Away    *Team
	Scores  map[string]interface{}
	RawData interface{}
}

type Dictionary map[string]string

func main() {
	opts := &socketio.Options{
		Transport: "websocket",
		Query: map[string]string{
			"gid":       "7b73a0d9b342d9f1",
			"token":     "53ea1de9-38d4-406c-ac56-dd344ee2ff6e",
			"id":        "Tesqedix5c8c8e4aa4fb4a84ac819002d0e2615e",
			"rid":       "2",
			"EIO":       "3",
			"transport": "websocket",
		},
		Header: map[string][]string{
			"Origin": {"https://i875ib.zmn2658.com"},
		},
	}

	client, err := socketio.NewClient("https://3qvsm5.zmn2658.com", opts)
	if err != nil {
		log.Fatalf("连接失败: %v", err)
	}
	log.Println("----连接中----")
	var (
		dictMutex  sync.RWMutex
		dict       Dictionary = make(Dictionary)
		teamsMutex sync.RWMutex
		teams      = make(map[string]*Team)
	)
	log.Println("----连接中1----")
	client.On("connect", func() {
		log.Println("[连接成功]")
	})
	log.Println("----连接中2----")
	client.On("disconnect", func() {
		log.Println("[断开连接]")
	})
	log.Println("----连接中3----")
	client.On("d", func(data interface{}) {
		// 字典事件
		rawDict, ok := data.(map[string]interface{})
		if !ok {
			log.Println("[字典] 数据格式不对")
			return
		}
		dictMutex.Lock()
		for k, v := range rawDict {
			if strV, ok := v.(string); ok {
				dict[k] = strV
			}
		}
		dictMutex.Unlock()
		log.Printf("[字典] 缓存字段映射 %d 条", len(dict))
	})

	client.On("teams", func(data interface{}) {
		bs, err := json.Marshal(data)
		if err != nil {
			log.Println("[球队] 序列化失败:", err)
			return
		}
		var teamList []Team
		if err := json.Unmarshal(bs, &teamList); err != nil {
			log.Println("[球队] 反序列化失败:", err)
			return
		}
		teamsMutex.Lock()
		for i := range teamList {
			teams[teamList[i].ID] = &teamList[i]
		}
		teamsMutex.Unlock()
		log.Printf("[球队] 缓存球队 %d 个", len(teamList))
	})

	client.On("m", func(data interface{}) {
		arr, ok := data.([]interface{})
		if !ok || len(arr) < 2 {
			log.Println("[比赛] 数据格式不对")
			return
		}
		rawMatches, ok := arr[1].([]interface{})
		if !ok {
			log.Println("[比赛] 第二个元素不是数组")
			return
		}
		for _, rawMatch := range rawMatches {
			matchArr, ok := rawMatch.([]interface{})
			if !ok {
				continue
			}
			match := parseMatch(matchArr, dict, &teamsMutex, teams)
			if match != nil {
				printMatch(match)
			}
		}
	})
	log.Println("----连接中4----")
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, os.Interrupt)
	<-quit

	log.Println("退出程序")
}

func parseMatch(raw []interface{}, dict Dictionary, teamsMutex *sync.RWMutex, teams map[string]*Team) *Match {
	if len(raw)%2 != 0 {
		return nil
	}

	fields := make(map[string]interface{})

	dictMutex := sync.RWMutex{}
	dictMutex.Lock()
	defer dictMutex.Unlock()

	for i := 0; i < len(raw); i += 2 {
		key, ok1 := raw[i].(string)
		value := raw[i+1]
		if !ok1 {
			switch v := raw[i].(type) {
			case float64:
				key = fmt.Sprintf("%.0f", v)
			case int:
				key = fmt.Sprintf("%d", v)
			default:
				key = fmt.Sprintf("%v", v)
			}
		}
		if realKey, ok := dict[key]; ok {
			fields[realKey] = value
		} else {
			fields[key] = value
		}
	}

	match := &Match{
		Scores:  make(map[string]interface{}),
		RawData: raw,
	}

	if idVal, ok := fields["match_id"]; ok {
		match.ID = fmt.Sprintf("%v", idVal)
	} else if idVal, ok := fields["m0"]; ok {
		match.ID = fmt.Sprintf("%v", idVal)
	}
	if homeID, ok := fields["home_team_id"]; ok {
		match.HomeID = fmt.Sprintf("%v", homeID)
	} else if homeID, ok := fields["h0"]; ok {
		match.HomeID = fmt.Sprintf("%v", homeID)
	}
	if awayID, ok := fields["away_team_id"]; ok {
		match.AwayID = fmt.Sprintf("%v", awayID)
	} else if awayID, ok := fields["a0"]; ok {
		match.AwayID = fmt.Sprintf("%v", awayID)
	}

	teamsMutex.RLock()
	match.Home = teams[match.HomeID]
	match.Away = teams[match.AwayID]
	teamsMutex.RUnlock()

	for k, v := range fields {
		if k != "match_id" && k != "m0" && k != "home_team_id" && k != "h0" && k != "away_team_id" && k != "a0" {
			match.Scores[k] = v
		}
	}

	return match
}

func printMatch(m *Match) {
	homeName := "未知主队"
	awayName := "未知客队"
	if m.Home != nil {
		homeName = m.Home.Name
	}
	if m.Away != nil {
		awayName = m.Away.Name
	}

	scoreStrs := []string{}
	for k, v := range m.Scores {
		scoreStrs = append(scoreStrs, fmt.Sprintf("%s=%v", k, v))
	}

	fmt.Printf("比赛ID:%s  %s VS %s  比分信息: %s\n", m.ID, homeName, awayName, strings.Join(scoreStrs, ", "))
}
